/**
 * This software was produced for the U. S. Government
 * under Contract No. FA8721-09-C-0002, and is
 * subject to the Rights in Noncommercial Computer Software
 * and Noncommercial Computer Software Documentation Clause
 * (DFARS) 252.227-7014 (JUN 1995)
 * 
 * (c) 2009 The MITRE Corporation. All Rights Reserved.
 *
 * SPMIF to OPNET Translator
 * Author: EWALTERS
 * Created: 4:11:13 PM, Nov 2, 2007
 * MITRE Corporation
 */
package com.mitre.spmif2opnet.analysis;

import java.util.BitSet;
import java.util.Hashtable;
import java.util.Map;

import com.mitre.spmif2opnet.analysis.ast.Scenario;

/**
 * This class transforms S-PMIF priorities to OPNET priorities by keeping the priority
 *  values distinct and maintaining the order (as opposed to scaling), but moving the
 *  priority values to withing OPNET range.  
 */
public class OrderedPriorities extends Priorities {

	/**
	 * Which priorities from the S-PMIF scale have we encountered?
	 * Used to make sure we can maintain distinct values.
	 */
	private BitSet _priorities_used;
	
	/**
	 * Default constructor
	 * @param type the type
	 */
	public OrderedPriorities(PriorityType type) {
		super(type);
		_priorities_used = new BitSet(new Double(_spmif_scale).intValue());
	}
	
	/**
	 * Override - add the priority to the map and set the used bit for the value
	 * @param proj_name project name
	 * @param scen scenario
	 */
	public void addSpmifPriority(String proj_name, Scenario scen) {
		super.addSpmifPriority(proj_name, scen);
		_priorities_used.set(scen.getPriority());
	}
	
	/**
	 * We could do this calculation one of two ways:
	 *  1) If the # of S-PMIF priority values > # of OPNET values, then start at the highest
	 *    S-PMIF value and map each distinct value to an OPNET value sequentially
	 *    If there for more values than mapping places, indicate an error.
	 *  2) If the # of OPNET values > # of S-PMIF values, map the priorities directly.
	 * 1) is currently the case!
	 */
	@Override
	public void calculate() throws AnalysisException {
		Map<Integer, Integer> pmap = new Hashtable<Integer, Integer>();
		if (_priorities_used.cardinality() > this._opnet_scale) {
			throw new AnalysisException("Too many priorities for OrderedPriorities to track!  Re-do your Priorities!");
		}
		for (int i = (new Double(_spmif_scale)).intValue() - 1,
				j = new Double(_opnet_scale).intValue() - 1; 
			    i >= 0; i--) {
			if (_priorities_used.get(i)) {
				pmap.put(i, j);
				j--;
			}
		}
		for (String id : this._spmif_priorities.keySet()) {
			this._opnet_priorities.put(id, pmap.get(this._spmif_priorities.get(id)));
		}
		this._processed = true;
	}

}
